package com.library.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.library.common.entity.MyPage;
import com.library.common.service.FileUploadService;
import com.library.common.utils.PageUtil;
import com.library.entity.UploadFiles;
import com.library.entity.dto.FileDtO;
import com.library.mapper.UploadFilesMapper;
import com.library.service.UploadFilesService;
import com.library.util.FileUtils;
import com.library.util.MoJiCommonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * <p>
 * 文件管理 服务实现类
 * </p>
 *
 * @author mds.
 * @since 2023-04-19
 */
@Slf4j
@Service
public class UploadFilesServiceImpl extends ServiceImpl<UploadFilesMapper, UploadFiles> implements UploadFilesService {

    @Resource
    private UploadFilesMapper uploadFilesMapper;

    @Resource
    private FileUploadService fileUploadService;

    @Value("${upload.files.path}")
    private String uploadPath;

    @Value("${upload.files.testHost}")
    private String testHost;

    @Override
    public String uploadPicture(MultipartFile file, String type) {

        //0.图片校验（图片是否为空）
        if (file.isEmpty()) {
            throw new RuntimeException("请选择图片！");
        }
//        if (billNo == null || "".equals(billNo)) {
//            throw new RuntimeException("请选择单据号码！");
//        }
//        if (billTypeCode == null || "".equals(billTypeCode)) {
//            throw new RuntimeException("请选择单据类型！");
//        }
        if (type == null || "".equals(type)) {
            type = "local";
        }
        if (!"local".equals(type) && !"oss".equals(type)) {
            throw new RuntimeException("传输地址异常，请刷新后重试！");
        }

        //1.获取原来的文件名和后缀
        String fileName = file.getOriginalFilename();
        if (fileName == null || "".equals(fileName)) {
            throw new RuntimeException("文件名异常，请刷新后重试！");
        }
        String ext = fileName.substring(fileName.lastIndexOf("."));
        String upperCase = checkExt(fileName.substring(fileName.lastIndexOf(".") + 1));
        long size = file.getSize();
        String printSize = getPrintSize(size);

        fileName = fileName.replace(" ", "_"); //把"空格"替换为 "_"

        //3.生成一个新的文件名（以防有重复的名字存在导致被覆盖）
        String path = "";

        if ("local".equals(type)) {
            //本地
            String uuid = UUID.randomUUID().toString().replace("-", "");
            String newName = uuid + ext;
            //拼接图片上传的路径 url+图片名
            ApplicationHome applicationHome = new ApplicationHome(this.getClass());
            String pre = applicationHome.getDir().getParentFile().getParentFile().getAbsolutePath() + "\\src\\main\\resources\\static\\images\\";
            String path2 = pre + newName;//（暂时这样存储，后期优化）
            path = uploadPath + newName;
            try {
                log.debug("上传文件路径为：======" + path2);
                file.transferTo(new File(path2));
            } catch (IOException e) {
                throw new RuntimeException("调用上传图片失败，请稍后重试！" + e);
            }

        } else {
            //1.先判断是否是图片
            //2.判断图片大小是否先进行压缩再进行上传OSS
            Boolean bool = FileUtils.isImage(file);
            //oss
            try {
                if (!bool || file.getSize() < 1024) {//非图片类型或者文件类型小于1024kb则直接上传oss
                    //path = fileUploadService.saveAliyun(file);
                    path = fileUploadService.saveHuaWeiYun(file);
                } else {//大于1024kb的图片类型需要先进行上传压缩处理然后再进行上传oss
                    //path = fileUploadService.saveAliyun(file);
                    path = fileUploadService.saveHuaWeiYun(file);
                }

            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return path;
    }

    @Override
    public MyPage<UploadFiles> queryByPage(FileDtO uploadFiles) {
        PageHelper.startPage(uploadFiles.getPageNum(), uploadFiles.getPageSize());
        LambdaQueryWrapper<UploadFiles> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UploadFiles::getIsDelete, 0L);
        queryWrapper.orderByDesc(UploadFiles::getUploadDate);

        List<UploadFiles> page = this.list(queryWrapper);
        PageInfo<UploadFiles> info = new PageInfo<>(page);
        return PageUtil.PageInfo2MyPage(info);
    }

    @Override
    public List<UploadFiles> selFilesByNo(String billNo, String billTypeCode) {
        LambdaQueryWrapper<UploadFiles> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UploadFiles::getIsDelete, 0L);
        queryWrapper.eq(UploadFiles::getBillNo, billNo);
        queryWrapper.eq(UploadFiles::getBillTypeCode, billTypeCode);
        queryWrapper.orderByDesc(UploadFiles::getUploadDate);

        List<UploadFiles> list = this.list(queryWrapper);

        return list;
    }

    @Override
    public boolean deleteFiles(Long id) {
        UploadFiles byId = this.getById(id);

        if (byId == null || byId.getIsDelete() == 1L) {
            throw new RuntimeException("文件不存在，请刷新后重试！");
        }

        byId.setIsDelete(1L);
        byId.setDelDate(new Date());
        String loginId = MoJiCommonUtils.getId();
        byId.setDelUserId(loginId);

        return updateById(byId);
    }


    //通用文件类型判断(判断允许上传的文件类型，并返回对应类型的大小写)
    String checkExt(String ext) {

        String upperCase = ext.toUpperCase();
        String lowerCase = ext.toLowerCase();


        String lowerCase2 = "*." + lowerCase + ";";

        String str = "[*.sql;*.dxf;*.prj;*.jfif;*.tif;*.tiff;*.css;*.icon;*.properties;*.yml;*.log;*.mpg;*.js;*.htm;*.html;*.xml;*.wmv;*.mp4;*.avi;*.mp3;*.rm;*.rmvb;*.3gp;*.mov;*.m4v;*.wav;*.jpeg;*.png;*.jpg;*.gif;*.bmp;*.xls;*.xlsx;*.doc;*.docx;*.ppt;*.pptx;*.txt;*.rar;*.zip;*.pdf;*.jar;]";

        if (!str.contains(lowerCase2)) {
            throw new RuntimeException("只能上传[*.sql;*.dxf;*.prj;*.jfif;*.tif;*.tiff;*.css;*.icon;*.properties;*.yml;*.log;*.mpg;*.js;*.htm;*.html;*.xml;*.wmv;*.mp4;*.avi;*.mp3;*.rm;*.rmvb;*.3gp;*.mov;*.m4v;*.wav;*.jpeg;*.png;*.jpg;*.gif;*.bmp;*.xls;*.xlsx;*.doc;*.docx;*.ppt;*.pptx;*.txt;*.rar;*.zip;*.pdf;*.jar;]格式的文件");
        }

        return upperCase;
    }

    public static String getPrintSize(long size) {
        //如果字节数少于1024，则直接以B为单位，否则先除于1024，后3位因太少无意义
        if (size < 1024) {
            return String.valueOf(size) + "B";
        } else {
            size = size / 1024;
        }
        //如果原字节数除于1024之后，少于1024，则可以直接以KB作为单位
        //因为还没有到达要使用另一个单位的时候
        //接下去以此类推
        if (size < 1024) {
            return String.valueOf(size) + "KB";
        } else {
            size = size / 1024;
        }
        if (size < 1024) {
            //因为如果以MB为单位的话，要保留最后1位小数，
            //因此，把此数乘以100之后再取余
            size = size * 100;
            return String.valueOf((size / 100)) + "."
                    + String.valueOf((size % 100)) + "MB";
        } else {
            //否则如果要以GB为单位的，先除于1024再作同样的处理
            size = size * 100 / 1024;
            return String.valueOf((size / 100)) + "."
                    + String.valueOf((size % 100)) + "GB";
        }
    }
}
